package com.piece.blog.service;

import com.piece.blog.model.ArticleComment;
import com.piece.blog.repository.ArticleCommentRepository;
import com.piece.core.framework.enums.StatusType;
import com.piece.core.jpa.repository.BaseService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.PostConstruct;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;

@Service
@Transactional
public class ArticleCommentService extends BaseService<ArticleComment, String> {

    @Autowired
    private ArticleCommentRepository articleCommentRepository;

    @PostConstruct
    public void initRepository() {
        setRepository(articleCommentRepository);
    }

    public List<ArticleComment> findByArticle(Long articleId) {
        String sql = "select distinct c.comment_id id, " +
                "c.comment_id commentId, " +
                "c.parent_id parentId, " +
                "c.comment_user_id commentUserId, " +
                "commentUser.user_id 'commentUser.id', " +
                "commentUser.user_name 'commentUser.nickName', " +
                "commentUser.avatar 'commentUser.avatar', " +
                "c.target_user_id targetUserId, " +
                "targetUser.user_id 'targetUser.id', " +
                "targetUser.user_name 'targetUser.nickName', " +
                "targetUser.avatar 'targetUser.avatar', " +
                "c.article_id articleId, " +
                "c.content content, " +
                "c.status status, " +
                "c.create_by createBy, " +
                "c.create_date createDate " +
                "from blog_article_comment c " +
                "left join tb_sys_user commentUser on commentUser.user_id = c.comment_user_id " +
                "left join tb_sys_user targetUser on targetUser.user_id = c.target_user_id " +
                "where c.status = " + StatusType.NORMAL.getCode() + " and c.article_id = " + articleId + " " +
                "order by c.create_date desc";
        List allComments = articleCommentRepository.findBySql(sql, null);
        if (allComments.size() > 0) {
            return findChildComments(allComments, 0l);
        }
        return allComments;
    }

    /**
     * 根据父节点的ID获取所有子节点
     */
    public List<ArticleComment> findChildComments(List<ArticleComment> list, long parentId) {
        List<ArticleComment> returnList = new ArrayList<>();
        for (Iterator<ArticleComment> iterator = list.iterator(); iterator.hasNext(); ) {
            ArticleComment comment = iterator.next();
            // 根据传入的某个父节点ID,遍历该父节点的所有子节点
            if (comment.getParentId() == parentId) {
                recursionFn(list, comment);
                returnList.add(comment);
            }
        }
        return returnList;
    }

    /**
     * 递归列表
     */
    private void recursionFn(List<ArticleComment> list, ArticleComment comment) {
        // 得到子节点列表
        List<ArticleComment> childList = getChildList(list, comment);
        comment.setChildrenList(childList);
        for (ArticleComment tChild : childList) {
            if (hasChild(list, tChild)) {
                // 判断是否有子节点
                Iterator<ArticleComment> it = childList.iterator();
                while (it.hasNext()) {
                    ArticleComment n = it.next();
                    recursionFn(list, n);
                }
            }
        }
    }

    /**
     * 判断是否有子节点
     */
    private boolean hasChild(List<ArticleComment> list, ArticleComment comment) {
        return getChildList(list, comment).size() > 0;
    }

    /**
     * 获取子节点列表
     */
    private List<ArticleComment> getChildList(List<ArticleComment> list, ArticleComment comment) {
        List<ArticleComment> clist = new ArrayList<>();
        Iterator<ArticleComment> it = list.iterator();
        while (it.hasNext()) {
            ArticleComment n = it.next();
            if (n.getParentId().longValue() == comment.getCommentId().longValue()) {
                clist.add(n);
            }
        }
        return clist;
    }
}
